﻿using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Diagnostics.SymbolStore;
using System.Linq;
using System.Reflection;
using System.Runtime.CompilerServices;
using System.Text;
using System.Threading.Tasks;

using Bootstrap5.Abstractions;

using Microsoft.AspNetCore.Components.Rendering;
using Microsoft.AspNetCore.Components;
using Microsoft.Extensions.DependencyInjection;

namespace Bootstrap5;

public static class BootstrapExtensions
{
    public static IServiceCollection AddBootstrap5(this IServiceCollection services, Action<BootstrapOptions> optionAction = default)
    {
        services.AddTransient<ICssClassBuilder, CssClassBuilder>()
            .AddTransient<BootstrapTriggerBuilder>()
            .AddScoped<IToastService,ToastService>()
            ;
        BootstrapOptions options = new();
        optionAction?.Invoke(options);
        return services;
    }

    public static string GetEnumCssClass(this object enumeration, string prefix = default)
    {
        if (enumeration is null || enumeration is not Enum)
        {
            return string.Empty;
        }

        var enumType = enumeration.GetType();
        var enumName = enumeration.ToString().ToLower();
        var fieldInfo = enumType.GetTypeInfo().GetDeclaredField(enumeration.ToString());

        if (fieldInfo == null)
        {
            return prefix + enumName;
        }

        var attr = fieldInfo.GetCustomAttribute<CssClassAttribute>();
        if (attr == null)
        {
            return prefix + enumName;
        }
        return prefix + attr.Name;
    }
    public static object GetEnumDefaultValue(this object enumeration) => enumeration.GetEnumDefaultValue(string.Empty);
    public static object GetEnumDefaultValue<T>(this object enumeration,T defaultValue=default)
    {
        if (enumeration is null || enumeration is not Enum)
        {
            return defaultValue;
        }

        var enumType = enumeration.GetType();
        var enumName = enumeration.ToString().ToLower();
        var fieldInfo = enumType.GetTypeInfo().GetDeclaredField(enumeration.ToString());

        if (fieldInfo == null)
        {
            return enumName;
        }

        var attr = fieldInfo.GetCustomAttribute<DefaultValueAttribute>();
        if (attr == null)
        {
            return enumName;
        }
        return attr.Value;
    }

    public static bool TryGetCustomeAttribute<TAttribute>(this Type type, out TAttribute attribute, bool inherit = default) where TAttribute : Attribute
    {
        attribute = type.GetCustomAttribute<TAttribute>(inherit);
        return attribute is not null;
    }

    public static bool TryGetCustomeAttribute<TAttribute>(this PropertyInfo property, out TAttribute attribute, bool inherit = default) where TAttribute : Attribute
    {
        attribute = property.GetCustomAttribute<TAttribute>(inherit);
        return attribute is not null;
    }

    public static void CreateCascadingValueComponent<TValue>(this BootstrapComponentBase component, RenderTreeBuilder builder, RenderFragment childContent, string name = default, bool isFixed = default)
    {
        builder.OpenRegion(100);
        builder.OpenComponent<CascadingValue<TValue>>(0);
        builder.AddAttribute(1, nameof(CascadingValue<TValue>.ChildContent), childContent);
        if (!string.IsNullOrEmpty(name))
        {
            builder.AddAttribute(2, nameof(CascadingValue<TValue>.Name), name);
        }
        builder.AddAttribute(3, nameof(CascadingValue<TValue>.IsFixed), isFixed);
        builder.AddAttribute(4, nameof(CascadingValue<TValue>.Value), component);
        builder.CloseComponent();
        builder.CloseRegion();
    }

    public static void CreateElement(this RenderTreeBuilder builder,int sequence, string elementName,  RenderFragment childContent = default,object attributes=default,bool condition=true)
    {
        if (!condition)
        {
            return;
        }

        builder.OpenRegion(sequence);
        builder.OpenElement(0,elementName);
        if(attributes is not null)
        {
            var index = 1;
            foreach (var item in attributes.GetType().GetProperties())
            {
                var name = item.Name;
                var value = item.GetValue(attributes);
                builder.AddAttribute(index, name, value);
                index++;
            }
        }
        if(childContent is not null)
        {
            builder.AddContent(100, childContent);
        }
        builder.CloseElement();
        builder.CloseRegion();
    }
    public static void CreateComponent<TComponent>(this RenderTreeBuilder builder, int sequence, RenderFragment childContent = default, object attributes = default)
        where TComponent:ComponentBase
    {
        builder.OpenRegion(sequence);
        builder.OpenComponent<TComponent>(0);

        if (attributes is not null)
        {
            var index = 1;
            foreach (var item in attributes.GetType().GetProperties())
            {
                var name = item.Name;
                var value = item.GetValue(attributes);
                builder.AddAttribute(index, name, value);
                index++;
            }
        }
        if (childContent is not null)
        {
            builder.AddContent(100, childContent);
        }
        builder.CloseComponent();
        builder.CloseRegion();
    }

    public static string GetColorTextClass(this Color color)
	{
		if (new[] { Color.Info,Color.Light,Color.Warning }.Contains(color))
		{
            return"text-dark";
        }
        return $"text-white";
    }
}
